home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / CBASE102.ARJ / BTLOCK.C < prev    next >
Text File  |  1991-09-23  |  6KB  |  255 lines

  1. /*    Copyright (c) 1989 Citadel    */
  2. /*       All Rights Reserved        */
  3.  
  4. /* #ident    "@(#)btlock.c    1.5 - 91/09/23" */
  5.  
  6. #include <ansi.h>
  7.  
  8. /* ansi headers */
  9. #include <errno.h>
  10. #ifdef AC_STDDEF
  11. #include <stddef.h>
  12. #endif
  13. #ifdef AC_STDLIB
  14. #include <stdlib.h>
  15. #endif
  16.  
  17. /* library headers */
  18. #include <blkio.h>
  19.  
  20. /* local headers */
  21. #include "btree_.h"
  22.  
  23. /* function declarations */
  24. #ifdef AC_PROTO
  25. static int resync(btree_t *btp);
  26. #else
  27. static int resync();
  28. #endif
  29.  
  30. /*man---------------------------------------------------------------------------
  31. NAME
  32.      btlock - btree lock
  33.  
  34. SYNOPSIS
  35.      #include <btree.h>
  36.  
  37.      int btlock(btp, ltype)
  38.      btree_t *btp;
  39.      int ltype;
  40.  
  41. DESCRIPTION
  42.      The btlock function controls the lock status of a btree.  The btp
  43.      argument is an open btree.  ltype indicates the target status of
  44.      the lock on the btree.
  45.  
  46.      The lock types available are:
  47.  
  48.           BT_UNLCK - unlock btree
  49.           BT_RDLCK - lock btree for reading
  50.           BT_WRLCK - lock btree for reading and writing
  51.           BT_RDLKW - lock btree for reading (wait)
  52.           BT_WRLKW - lock btree for reading and writing (wait)
  53.  
  54.      For the lock types which wait, btlock will not return until the
  55.      lock is available.  For the lock types which do not wait, if
  56.      the lock is unavailable because of a lock held by another process
  57.      a value of -1 is returned and errno set to EAGAIN.
  58.  
  59.      When a btree is unlocked, its cursor is set to null.
  60.  
  61.      The buffers are flushed before unlocking.
  62.  
  63.      btlock will fail if one or more of the following is true:
  64.  
  65.      [EAGAIN]       ltype is BT_RDLCK and btp is already write locked
  66.                     by another process, or ltype is BT_WRLCK and btp
  67.                     is already read or write locked by another
  68.                     process.
  69.      [EINVAL]       btp is is not a valid btree pointer.
  70.      [EINVAL]       ltype is not one of the valid lock types.
  71.      [BTECORRUPT]   btp is corrupt.
  72.      [BTENOPEN]     btp is not open.
  73.      [BTENOPEN]     ltype is BT_RDLCK or BT_RDLKW and btp is not
  74.                     opened for reading or ltype is BT_WRLCK or
  75.                     BT_WRLKW and btp is not open for writing.
  76.  
  77. SEE ALSO
  78.      btgetlck.
  79.  
  80. DIAGNOSTICS
  81.      Upon successful completion, a value of 0 is returned.  Otherwise,
  82.      a value of -1 is returned, and errno set to indicate the error.
  83.  
  84. ------------------------------------------------------------------------------*/
  85. #ifdef AC_PROTO
  86. int btlock(btree_t *btp, int ltype)
  87. #else
  88. int btlock(btp, ltype)
  89. btree_t *btp;
  90. int ltype;
  91. #endif
  92. {
  93.     int    bltype    = 0;        /* blkio lock type */
  94.  
  95.     /* validate arguments */
  96.     if (!bt_valid(btp)) {
  97.         errno = EINVAL;
  98.         return -1;
  99.     }
  100.  
  101.     /* check if btree not open */
  102.     if (!(btp->flags & BTOPEN)) {
  103.         errno = BTENOPEN;
  104.         return -1;
  105.     }
  106.  
  107.     /* check if btree not open for lock ltype */
  108.     switch (ltype) {
  109.     case BT_UNLCK:
  110.         btp->cbtpos.node = NIL;        /* set cursor to null */
  111.         btp->cbtpos.key = 0;
  112.         bltype = B_UNLCK;
  113.         break;
  114.     case BT_RDLCK:
  115.         if (!(btp->flags & BTREAD)) {
  116.             errno = BTENOPEN;
  117.             return -1;
  118.         }
  119.         bltype = B_RDLCK;
  120.         break;
  121.     case BT_RDLKW:
  122.         if (!(btp->flags & BTREAD)) {
  123.             errno = BTENOPEN;
  124.             return -1;
  125.         }
  126.         bltype = B_RDLKW;
  127.         break;
  128.     case BT_WRLCK:
  129.         if (!(btp->flags & BTWRITE)) {
  130.             errno = BTENOPEN;
  131.             return -1;
  132.         }
  133.         bltype = B_WRLCK;
  134.         break;
  135.     case BT_WRLKW:
  136.         if (!(btp->flags & BTWRITE)) {
  137.             errno = BTENOPEN;
  138.             return -1;
  139.         }
  140.         bltype = B_WRLKW;
  141.         break;
  142.     default:
  143.         errno = EINVAL;
  144.         return -1;
  145.         break;
  146.     }
  147.  
  148.     /* lock btree file */
  149.     if (lockb(btp->bp, bltype, (bpos_t)0, (bpos_t)0) == -1) {
  150.         if (errno != EAGAIN) BTEPRINT;
  151.         return -1;
  152.     }
  153.  
  154.     /* set status bits in btree control structure */
  155.     switch (ltype) {
  156.     case BT_UNLCK:
  157.         btp->flags &= ~BTLOCKS;
  158.         break;
  159.     case BT_RDLCK:
  160.     case BT_RDLKW:
  161.         /* if previously unlocked, re-sync with file */
  162.         if (!(btp->flags & BTLOCKS)) {
  163.             if (resync(btp) == -1) {
  164.                 BTEPRINT;
  165.                 return -1;
  166.             }
  167.         }
  168.         btp->flags |= BTRDLCK;
  169.         btp->flags &= ~BTWRLCK;
  170.         break;
  171.     case BT_WRLCK:
  172.     case BT_WRLKW:
  173.         /* if previously unlocked, re-sync with file */
  174.         if (!(btp->flags & BTLOCKS)) {
  175.             if (resync(btp) == -1) {
  176.                 BTEPRINT;
  177.                 return -1;
  178.             }
  179.         }
  180.         btp->flags |= (BTRDLCK | BTWRLCK);
  181.         break;
  182.     default:
  183.         BTEPRINT;
  184.         errno = BTEPANIC;
  185.         return -1;
  186.         break;
  187.     }
  188.  
  189.     return 0;
  190. }
  191.  
  192. /* resync:  re-synchronize with file */
  193. #ifdef AC_PROTO
  194. static int resync(btree_t *btp)
  195. #else
  196. static int resync(btp)
  197. btree_t *btp;
  198. #endif
  199. {
  200.     size_t        oldkeysize    = btp->bthdr.keysize;
  201.     unsigned long    oldheight    = 0;
  202.     btpos_t    *    sp        = NULL;
  203.     int        terrno        = 0;        /* tmp errno */
  204.  
  205.     /* save old tree height */
  206.     oldheight = btp->bthdr.height;
  207.  
  208.     /* read in header */
  209.     if (bgeth(btp->bp, &btp->bthdr) == -1) {
  210.         BTEPRINT;
  211.         return -1;
  212.     }
  213.  
  214.     /* check for corruption */
  215.     if (btp->bthdr.flags & BTHMOD) {
  216.         errno = BTECORRUPT;
  217.         return -1;
  218.     }
  219.  
  220.     /* if first time locked, do setup */
  221.     if (oldkeysize == 0) {
  222.         /* allocate memory for btree */
  223.         if (bt_alloc(btp) == -1) {
  224.             BTEPRINT;
  225.             btp->bthdr.keysize = 0;
  226.             return -1;
  227.         }
  228.         /* set up buffering */
  229.         if (bsetvbuf(btp->bp, NULL, bt_blksize(btp), BTBUFCNT) == -1) {
  230.             BTEPRINT;
  231.             terrno = errno;
  232.             bt_free(btp);
  233.             btp->bthdr.keysize = 0;
  234.             errno = terrno;
  235.             return -1;
  236.         }
  237.     }
  238.  
  239.     /* adjust for new tree height */
  240.     if (btp->bthdr.height != oldheight) {
  241.         sp = (btpos_t *)realloc(btp->sp, (size_t)(btp->bthdr.height + 1) * sizeof(*sp));
  242.         if (sp == NULL) {
  243.             BTEPRINT;
  244.             errno = ENOMEM;
  245.             return -1;
  246.         }
  247.         btp->sp = sp;
  248.         sp = NULL;
  249.         btp->sp[btp->bthdr.height].node = NIL;
  250.         btp->sp[btp->bthdr.height].key = 0;
  251.     }
  252.  
  253.     return 0;
  254. }
  255.